You're reading an pre-release version of this documentation.
For the latest stable release version, please have a look at master.

How to use a local SpinalHDL clone as project dependency

The default way to use SpinalHDL is by using the released version of it as is automatically downloaded by sbt or mill. Living on the cutting edge, you might want to use the upstream and non released dev branch from git directly. Be it just because you want to use a new shiny feature or because you want to test your own extension to Spinal (please consider upstreaming it by opening a PR) within a project.

As an example of where this is used you can also refer to VexiiRiscv.

Create local git clone of SpinalHDL

cd /somewhere
git clone --depth 1 -b dev https://github.com/SpinalHDL/SpinalHDL.git

In the command above you can replace dev by the name of the branch you want to checkout. --depth 1 prevents from downloading the repository history.

Configure buildsystem

Depending on which tool you use, instruct either sbt or mill to load the local git folder as dependency:

Configure sbt (update build.sbt)

ThisBuild / version := "1.0"              // change as needed
ThisBuild / scalaVersion := "2.12.18"     // change as needed
ThisBuild / organization := "org.example" // change as needed

val spinalRoot = file("/somewhere/SpinalHDL")
lazy val spinalIdslPlugin = ProjectRef(spinalRoot, "idslplugin")
lazy val spinalSim = ProjectRef(spinalRoot, "sim")
lazy val spinalCore = ProjectRef(spinalRoot, "core")
lazy val spinalLib = ProjectRef(spinalRoot, "lib")

lazy val projectname = (project in file("."))
.settings(
   Compile / scalaSource := baseDirectory.value / "hw" / "spinal",
).dependsOn(spinalIdslPlugin, spinalSim, spinalCore, spinalLib)

scalacOptions += (spinalIdslPlugin / Compile / packageBin / artifactPath).map { file =>
  s"-Xplugin:${file.getAbsolutePath}"
}.value

fork := true

Configure mill (update build.sc)

import mill._, scalalib._

import $file.^.SpinalHDL.build
import ^.SpinalHDL.build.{core => spinalCore}
import ^.SpinalHDL.build.{lib => spinalLib}
import ^.SpinalHDL.build.{idslplugin => spinalIdslplugin}

val spinalVers = "1.10.2a"
val scalaVers = "2.12.18"

object projectname extends RootModule with SbtModule {
   def scalaVersion = scalaVers
   def sources = T.sources(
      this.millSourcePath / "hw" / "spinal"
   )

   def idslplugin = spinalIdslplugin(scalaVers)
   def moduleDeps = Seq(
      spinalCore(scalaVers),
      spinalLib(scalaVers),
      idslplugin
   )
   def scalacOptions = super.scalacOptions() ++ idslplugin.pluginOptions()
}

Note the line import $file.^.SpinalHDL.build. It is using ammonite REPL magic $file to look up the build.sc of SpinalHDL. (The ^ moves up one directory from the current.) This is assuming the following directory structure:

/somewhere
|-SpinalHDL   # <-- cloned spinal git
| |-build.sc
|-projectname
| |-build.sc  # <-- your project, mill is ran from here

Done

Note the addition to scalacOptions. Without it, compiling any Spinal project might produce countless SCOPE VIOLATION or HIERARCHY VIOLATION errors because the idslplugin of spinal is not actually invoked.

After the changes, the next compilation of your project will take a considerable amount of time (~2 minutes). This is only for the first compile. After this, your project should compile as usual.